﻿#region Copyright Jonathan Quiros

//	
// All rights are reserved. Reproduction or transmission in whole or in 
// part, in any form or by any means, electronic, mechanical or otherwise, 
// is prohibited without the prior written consent of the copyright owner.
//
// Filename: BaseController.cs
//

#endregion

using System;
using System.Configuration;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Security;
using Novagoal.Logic;
using Novagoal.Models;
using Ids.Web.DataObjects;
using Ids.Web.Security;
using Microsoft.Web.Mvc;
using Novagoal.Utils;

namespace Novagoal.Website.WebApp.Controllers
{
    public class UserInformation : UserInfo
    {
        public Person Person { get; set; }
    }

    public class BaseController : SecuredController
    {
        #region Properties

        protected string language;
        protected readonly UsersLogic UsersLogic;
        public IApplicationSettings ApplicationSettings { get; set; }
        public IEmailSender EmailSender { get; set; }

        #endregion

        #region Public Methods

        /// <summary>
        /// Initializes a new instance of the <see cref="BaseController"/> class.
        /// </summary>
        public BaseController(UsersLogic usersLogic)
        {
            UsersLogic = usersLogic;
            CreateSecurityContext();
            language = "";
        }

        protected RedirectToRouteResult RedirectToAction<T>(Expression<Action<T>> action) where T : Controller
        {
            return ControllerExtensions.RedirectToAction(this, action);
        }

        public UserInformation GetUserInformation()
        {
            return SecurityContext.User as UserInformation;
        }

        /// <summary>
        /// Creates the security context.
        /// </summary>
        private void CreateSecurityContext()
        {
            if (SecurityContext == null)
            {
                var identity = System.Web.HttpContext.Current.User.Identity;
                if (identity.IsAuthenticated && !string.IsNullOrEmpty(identity.Name))
                {
                    var user = UsersLogic.GetUser(identity.Name);

                    SecurityContext = new SecurityContext
                    {
                        User = new UserInformation
                        {
                            Id = user.Id,
                            Name = user.Person.FullName,
                            Username = user.Person.EmailAddress,
                            Role = user.Role.Name,
                            RoleId = user.Role.Id,
                            Person = user.Person
                        }
                    };
                }
                else
                {
                    System.Web.HttpContext.Current.Session.Abandon();
                    FormsAuthentication.SignOut();
                    FormsAuthentication.RedirectToLoginPage();
                }
            }
        }

        protected override void OnException(ExceptionContext filterContext)
        {
            base.OnException(filterContext);
            filterContext.ExceptionHandled = true;

            SendMail(filterContext.Exception);

            if (filterContext.Exception is HttpException)
            {
                var ex = filterContext.Exception as HttpException;
                var code = ex.GetHttpCode();
                switch (code)
                {
                    case (int)HttpStatusCode.Forbidden:
                        filterContext.Result = View("Unauthorized");
                        break;
                    case (int)HttpStatusCode.NotFound:
                        filterContext.Result = View("NotFound");
                        break;
                    default:
                        filterContext.Result = View("Unexpected");
                        break;
                }
            }
            else
            {
                filterContext.Result = View("Unexpected");
            }
        }

        #endregion

        #region Private Methos

        private void SendMail(Exception exception)
        {
            var mailMessage = CreateMailMessage(exception);
            var settingsReader = new AppSettingsReader();
            var to = settingsReader.GetValue("ErrorMail", typeof(string)).ToString();

            EmailSender.SendEmail(null, to, "NovaGoal (Unhandled Exception)", mailMessage);
        }

        private string CreateMailMessage(Exception exception)
        {
            var versionNumber = Helpers.VersionNumberHelper.RenderVersionNumber(HttpContext);

            var strBody = new StringBuilder();
            strBody.AppendLine("<div style='font-family: Arial, Helvetica, sans-serif;font-size: 12px'>");
            strBody.AppendFormat("<b>Error Message:</b> {0} <br/>", exception.Message);
            strBody.AppendFormat("<b>Date: </b> {0} at {1}<br/>", DateTime.Now.ToLongDateString(), DateTime.Now.ToLongTimeString());
            strBody.AppendFormat("<b>Request: </b> {0} <br/>", System.Web.HttpContext.Current.Request.Url);
            strBody.AppendFormat("<b>Version: </b> {0} <br/>", versionNumber);
            strBody.AppendFormat("<b>Username: </b> {0} <br/>", System.Web.HttpContext.Current.User.Identity.Name);

            strBody.AppendLine("<br/>");
            strBody.AppendLine("<div style='color:red'>EXCEPTION</div>");
            AppendExceptions(strBody, exception);

            return strBody.ToString();
        }

        private static void AppendExceptions(StringBuilder strBody, Exception ex)
        {
            strBody.AppendFormat("<b>Message:</b> {0} <br/>", ex.Message);

            if (!string.IsNullOrEmpty(ex.Source))
                strBody.AppendFormat("<b>Source:</b> {0} <br/>", ex.Source);

            if (ex.TargetSite != null)
                strBody.AppendFormat("<b>Target:</b> {0} <br/>", ex.TargetSite);

            if (!string.IsNullOrEmpty(ex.StackTrace))
            {
                strBody.AppendLine("<b>Stack Trace:</b><br/>");
                strBody.AppendLine(ex.StackTrace.Replace("\n", "<br/>"));
            }

            if (ex.InnerException != null)
            {
                strBody.AppendLine("<br/><br/>");
                strBody.AppendLine("<div style='color:red'>INNER EXCEPTION</div>");

                AppendExceptions(strBody, ex.InnerException);
            }
        }

        #endregion
    }
}
